home *** CD-ROM | disk | FTP | other *** search
- /*------------------------------------------------------------------------------
- *
- * Apple Developer Technical Support
- *
- *
- *
- * Program: AEObject-Edition Sample
- * File: Utilities.c -C Source
- *
- * by: C.K. Haun <TR>
- *
- * Copyright © 1990-1992 Apple Computer, Inc.
- * All rights reserved.
- *
- *------------------------------------------------------------------------------
- * This file contains some of our window handling routines. I created it
- * primarily to take some of the clutter out of the main.c file.
- * It also contains the clipboard handlers
- *----------------------------------------------------------------------------*/
-
- #define __GUTILS__
-
- #include "Sampdefines.h"
-
- #pragma segment Utils
-
- /* standardDialogFilter is _new_ and dispatches to the System 7 */
- /* standard dialog filter. Please see tech note #304 */
- /* for details on how this works, and why I am checking */
- /* for update events in this thing */
- /* Look right below for one for Alerts */
- pascal Boolean standardDialogFilter(DialogPtr theDialog, EventRecord *theEvent, short *itemHit)
- {
- if (theEvent->what == updateEvt && theEvent->message != theDialog ){
- WindowPtr theWindow = (WindowPtr)theEvent->message;
- /* draw my window if it's really mine */
- if(IsMyWindow(theWindow)){
- DrawIt((WindowPtr)theWindow);
- *itemHit = 0;
- return(false); /* tell the dialog manager I handled this event */
- }
- } else {
- ModalFilterUPP stdProc;
- GetStdFilterProc(&stdProc);
- return CallModalFilterProc(stdProc, theDialog, theEvent, itemHit);
- }
- } /* end standardDialogFilter */
-
- pascal Boolean standardAlertFilter(DialogPtr theDialog, EventRecord *theEvent, short *itemHit)
- {
- Boolean returnVal = false;
- if(theEvent->what == updateEvt && theEvent->message != theDialog ){
- WindowPtr theWindow = (WindowPtr)theEvent->message;
- /* draw my window if it's really mine */
- if(IsMyWindow(theWindow)){
- DrawIt((WindowPtr)theWindow);
- *itemHit = 0;
- returnVal = false;
- }
- } else {
- /* for alerts we have to check for keys ourselves, since we didn't have a chance to */
- /* call SetDialogCancel or anything */
-
- if ((theEvent->what == keyDown) || (theEvent->what == autoKey)) {
- short tempItem; Handle tempHandle;
- Rect tempRect;
- char theKey = theEvent->message & charCodeMask;
- switch (theKey) {
- long tilticks;
- case kReturnKey:
- case kEnterKey: /* enter key */
- /* This filters for Return or Enter as item 1, and Esc as item 2 */
- *itemHit = 1; /* change whatever the current item is to the OK item */
- /* now we need to invert the button */
- GetDialogItem(theDialog, 1, &tempItem, &tempHandle, &tempRect);
- if(tempItem == ctrlItem){
- /* double check for the unlikely event that this is _not_ a button */
- HiliteControl(SnatchHandle(theDialog, ok), inButton);
- Delay(8, &tilticks); /* wait about 8 ticks so they can see it */
- HiliteControl(SnatchHandle(theDialog, ok), false);
-
- returnVal = true;
- }
- break;
- /* This filters the escape key as the same as item 2 (the canx button, usually ) */
- case kEscKey:
- *itemHit = 2;
- if(tempItem == ctrlItem){
- /* much more likely that this may not be a button */
-
- HiliteControl(SnatchHandle(theDialog, cancel), inButton);
- Delay(8, &tilticks); /* wait about 8 ticks so they can see it */
- HiliteControl(SnatchHandle(theDialog, cancel), false);
- returnVal = true;
- }
- break;
- }
-
- }
-
-
-
-
-
-
-
-
-
- }
- return(returnVal);
- } /* end standardDialogFilter */
-
- /* Gets the ControlHandle for the item you want in the dialog box thebox. */
- /* Handy for setting checkboxes and radio buttons */
- ControlHandle SnatchHandle(DialogPtr thebox, short theGetItem)
- {
- short itemtype;
- Rect itemrect;
- Handle thandle;
- GetDialogItem(thebox, theGetItem, &itemtype, &thandle, &itemrect);
- return((ControlHandle)thandle);
- } /* end SnatchHandle */
-
- /* MakeRect converts two points into a rect. */
- /* it also insures that the rect is not reversed */
- void MakeRect(Point *aPoint, Point *bPoint, Rect *putRect)
- {
- short temp;
- putRect->top = aPoint->v;
- putRect->left = aPoint->h;
- putRect->bottom = bPoint->v;
- putRect->right = bPoint->h;
- if (putRect->top > putRect->bottom) {
- temp = putRect->bottom;
- putRect->bottom = putRect->top;
- putRect->top = temp;
- }
- if (putRect->left > putRect->right) {
- temp = putRect->right;
- putRect->right = putRect->left;
- putRect->left = temp;
- }
- if (putRect->right == putRect->left)
- putRect->left++;
- if (putRect->bottom == putRect->top)
- putRect->bottom++;
- } /* end MakeRect */
-
-
- /* ties two P strings together. Haven't we all written this at one time or another???? */
- void AppendString(Str255 target, Str255 appendIt)
- {
- BlockMove((Ptr)(appendIt + 1), (Ptr)(target + (target[0])+1), appendIt[0]);
- target[0] += appendIt[0];
- } /* end AppendString */
-
- /* PureCursor checks to see if the last keystroke was a 'pure' cursor */
- /* moving keystroke. This is important for setting Undo for text typing, */
- /* if I had put that in */
- Boolean PureCursor(char theKey)
- {
- register qq;
- char curChars[4] = {
- kLeftArrow, kRightArrow, kUpArrow, kDownArrow
- };
- Boolean result = false;
- for (qq = 0; qq < 4; qq++) {
- if (theKey == curChars[qq])
- result = true;
- }
- return(result);
-
- } /* end PureCursor */
-
- /* This tries as hard as it can to resize a handle, avoiding the problem SetHandleSize */
- /* has when a block is surrounded by locked stuff. */
- /* Of course if you use this, you can only have one copy of the handle around and you */
- /* always must reference that handle, since the master pointer contained within it */
- /* can change during the ReallocateHandle call. But you should be doing that anyway (nag nag nag) */
- OSErr MySetHandleSize(Handle theHandle, Size theSize)
- {
- OSErr memErr;
- Handle tempHand = theHandle;
- SetHandleSize(theHandle, theSize);
- memErr = MemError();
- if (!memErr)
- return(noErr);
- /* could not resize the handle. Why? */
- if (memErr != memFullErr)
- return(memErr); /* not something we can deal with */
- /* either the memory is really not available, or there is a locked pointer
- * above the handle we're resizing. We'll try seeing if the memory
- * is actually there first. */
- ShowMe("\p mem err", memErr, __LINE__);
- if (!(CompactMem(theSize) >= theSize))
- return(MemError()); /* memory really is full, bail */
- /* OK, memory is available somewhere. Find it */
- HandToHand(&tempHand); /* copy the handle */
- ReallocateHandle(theHandle, theSize); /* resize by reallocation */
- HLock(tempHand);
- HLock(theHandle);
- BlockMove(*tempHand, *theHandle, GetHandleSize(theHandle)); /* only move the size of the target */
- HUnlock(theHandle);
- DisposeHandle(tempHand);
- } /* end MySetHandleSize */
-
- /* ShowMe is just a handy place to display a string and a number. */
- /* ••• NOTE: That I'm calling AEInteractWithUser here, instead */
- /* of just blasting up an alert */
- void ShowMe(Str255 in, OSErr aevtErr, short lineNo)
- {
- NMRec myNotification;
- Str255 nmWords;
- Str32 theGuy;
- Str32 theLine;
- OSErr myErr;
- myNotification.qType =nmType ;
- myNotification.nmMark = nil;
- myNotification.nmIcon = nil;
- myNotification.nmSound = (Handle)-1;
- myNotification.nmStr =&nmWords ;
- myNotification.nmResp =nil ;
-
- GetIndString(&nmWords,kGeneralStrings,kErrorToSay);
- myErr = AEInteractWithUser(kAEDefaultTimeout, &myNotification, gCommonIdleFunctionUPP);
- if(myErr != errAENoUserInteraction ) {
- ModalFilterUPP upp = NewModalFilterProc(standardAlertFilter);
- InitCursor();
- NumToString((long)aevtErr, theGuy);
- NumToString((long)lineNo, theLine);
- ParamText(in, theGuy, theLine, "");
- Alert(129, upp);
- DisposeRoutineDescriptor(upp);
-
- }
- } /* end ShowMe */
-
- /* DoDiskEvents just checks the error code from the disk mount, */
- /* and puts up the 'Format' dialog (through DIBadMount) if need be */
- /* You can do much more here if you care about what disks are */
- /* in the drive */
- void DoDiskEvents(long dinfo) /* hi word is error code, lo word is drive number */
- {
- short hival, loval, tommy;
- Point fredpoint = {
- 40, 40
- };
- hival = HiWord(dinfo);
- loval = LoWord(dinfo);
- if (hival != noErr) /* something happened */ {
- tommy = DIBadMount(fredpoint, dinfo);
- }
- } /* end DoDiskEvents */
-
- /* CommonDStart is here just because I'm tired of typing GetNewDialog and */
- /* typing the d*mned (WindowPtr)-1 all the time. */
- /* It also sets up our default and cancel items, as expalined in TN #304 */
- DialogPtr CommonDStart(short DNumber, short set1, short set2)
- {
-
- DialogPtr tdial = GetNewDialog(DNumber, nil, (WindowPtr)-1);
- if (set1)
- SetControlValue(SnatchHandle(tdial, set1), true);
- if (set2)
- SetControlValue(SnatchHandle(tdial, set2), true);
- SetDialogDefaultItem(tdial, ok);
- SetDialogCancelItem(tdial, cancel);
-
- return(tdial);
- } /* end CommonDStart */
-
- /* PullRect either drags a rect around the screen (for subscribers) or pulls a rect */
- /* rubber-band wise for anything else. I'm not using DragGryRgn because I have to check some */
- /* intersections along the way */
- /* And since an Oval has the same calling conventions as a Rect, it calls this too */
- void PullRect(windowCHandle theWind, Rect *startRect, Boolean isOval, Boolean useRect, Boolean onlyCorner)
- {
-
- WindowPtr theWindow = FrontWindow();
- Rect oldRect;
- Point endPoint, thePoint;
- Boolean hreversed = false;
- Boolean vreversed = false;
- /* set up */
- if (useRect) {
- oldRect = *startRect;
- } else {
- oldRect.top = startRect->top = oldRect.bottom = startRect->bottom = gERecord.where.v;
- oldRect.right = startRect->right = oldRect.left = startRect->left = gERecord.where.h;
- }
- PenMode(srcXor); /* So we can rubberband */
- /* see if we're dragging the whole rect, or just pulling a corner out */
- if (onlyCorner) {
- while (StillDown()) { /* Keep doing this as long as the */
- /* user keeps the mouse down */
- GetMouse(&endPoint); /* Current mouse position in local */
- if (hreversed) {
- /* see if it flipped first */
- if (endPoint.h > startRect->right) {
- /* they flipped back */
- hreversed = false; /* and ignore this move */
- } else {
- /* still reversed */
- startRect->left = endPoint.h;
- }
- } else {
- if (endPoint.h < startRect->left) {
- hreversed = true;
- } else {
- startRect->right = endPoint.h;
- }
- }
- if (vreversed) {
- /* see if it flipped first */
- if (endPoint.v > startRect->bottom) {
- /* they flipped back */
- vreversed = false; /* and ignore this move */
- } else {
- /* still reversed */
- startRect->top = endPoint.v;
- }
- } else {
- if (endPoint.v < startRect->top) {
- vreversed = true;
- } else {
- startRect->bottom = endPoint.v;
- }
- }
-
- /* make sure we're not intersecting a text box */
- if (!InTextBox(theWind, startRect)) {
- if (*startRect != oldRect) { /* redraw the rect only if the mouse moved */
- if (isOval) {
- FrameOval(&oldRect);
- FrameOval(startRect);
- } else {
- FrameRect(&oldRect);
- FrameRect(startRect); /* draw the new rect */
- }
- oldRect = *startRect;
- }
- } else {
- *startRect = oldRect;
- }
- }
- } else {
- /* We're dragging the whole rectangle here */
- GetMouse(&thePoint);
- while (StillDown()) { /* keep doing it until they release the mouse */
-
- PenMode(patXor);
- if (!EqualRect(startRect, &oldRect)) {
- FrameRect(startRect); /* nasty way to put up a flashing border for the drag */
- FrameRect(startRect);
-
- }
- GetMouse(&endPoint);
- /* keep inside the window please, don't let them drag the */
- /* rectangle outside the window bounds */
- if ((PtInRect(endPoint, &(FrontWindow()->portRect)))) {
- if (endPoint != thePoint) {
- oldRect = *startRect;
- OffsetRect(startRect, endPoint.h - thePoint.h, endPoint.v - thePoint.v);
- if (!InTextBox(theWind, startRect)) {
- thePoint = endPoint;
- } else {
- *startRect = oldRect;
- FrameRect(startRect); /* nasty way to put up a flashing border for the drag */
- FrameRect(startRect);
- }
- }
- }
- }
- PenMode(normal);
-
- }
- PenMode(srcCopy);
- } /* end PullRect */
-
- /* DoAnts draws the marque box for the current selection. */
- /* Please note: No one else in the known universe does marching ants */
- /* like this but me. I happen to like this */
- void DoAnts(Rect *theRect)
- {
- static short nowPat = 0;
- static long timeToMarch = 0;
- WindowPtr theWind = FrontWindow();
- Pattern thePat;
- if(TickCount() > timeToMarch || timeToMarch == 0){
- if (theWind) {
- windowCHandle tempWC = (windowCHandle)GetWRefCon(theWind);
- if ((*tempWC)->hasSelection || theRect) {
- GetIndPattern(&thePat, 128, nowPat);
- nowPat++;
- if (nowPat == 8)
- nowPat = 0;
- PenMode(patXor);
- PenPat(&thePat);
- if (theRect)
- FrameRect(theRect);
- else
- FrameRect(&(*tempWC)->selectionRect);
- PenMode(normal);
- PenPat(&qd.black);
- }
- }
- timeToMarch = TickCount() + kMarchTime;
- }
-
-
- } /* end DoAnts */
-
- /* AdjustCursor change the cursor's shape, depending on its position. This also calculates
- the region where the current cursor resides (for WaitNextEvent). If the
- mouse is ever outside of that region, an event would be generated, causing
- this routine to be called, allowing us to change the region to the region
- the mouse is currently in.
- */
-
- void AdjustCursor(Point mouse, RgnHandle region)
- {
- WindowPtr window;
- RgnHandle specialRgn;
- RgnHandle tbRgn;
- Rect textRect;
- Rect globalPortRect;
- windowCHandle shortName;
- window = FrontWindow(); /* we only adjust the cursor when we are in front */
- if (!window){
- SetEmptyRgn(region);
- return; /* ignore also if we have no open doc windows */
- }
- if (((WindowPeek)window)->windowKind == kClipboardWindow || ((WindowPeek)window)->windowKind == kAEStatusWindow) {
- InitCursor();
- SetEmptyRgn(region); /* don't care if a doc window not frontmost */
- return;
- }
- if ((!gInBackground) && (IsMyWindow(window))) {
- specialRgn = NewRgn();
- shortName = (windowCHandle)GetWRefCon(window);
- /* calculate specialRgn */
- globalPortRect = window->portRect;
- LocalToGlobal((Point *)&globalPortRect);
- LocalToGlobal((Point *)&globalPortRect.bottom);
- RectRgn(specialRgn, &globalPortRect);
- if((*shortName)->boxHandle){
- textRect = (*shortName)->textBox;
- LocalToGlobal((Point *)&textRect);
- LocalToGlobal((Point *)&textRect.bottom);
- tbRgn = NewRgn();
- OpenRgn();
- FrameRect(&textRect);
- CloseRgn(tbRgn);
- DiffRgn(specialRgn,tbRgn,specialRgn);
- DisposeRgn(tbRgn);
-
-
-
- }
- /* change the cursor and the region parameter */
-
- if (PtInRect(mouse, &globalPortRect)) {
- short temp;
-
- temp = actsToIDs[(*shortName)->currentAction];
- SetMyCursor(temp);
- /* if textbox then poke hole for text box */
- if((*shortName)->boxHandle){
- textRect = (*shortName)->textBox;
- LocalToGlobal((Point *)&textRect);
- LocalToGlobal((Point *)&textRect.bottom);
- if(PtInRect(mouse, &textRect)){
- InitCursor();
- RectRgn(specialRgn, &textRect);
- }
- }
- CopyRgn(specialRgn, region);
- } else { /* outside */
-
- InitCursor();
- /* make a region that's everything _but_ our windows vis region */
- /* Uhhh, I was asking for the gray region here, but that doesn't */
- /* include the menu bar, so you really do need to go full open */
- SetRectRgn(region, kExtremeNeg, kExtremeNeg,
- kExtremePos, kExtremePos);
- DiffRgn(region, specialRgn, region);
- }
- /* get rid of our local regions */
- DisposeRgn(specialRgn);
- }
- }
-
- /* end AdjustCursor*/
-
- Boolean CompareFSSpecs(FSSpecPtr spec1,FSSpecPtr spec2)
- {
- Boolean returnVal = false;
-
- if((spec1->vRefNum == spec2->vRefNum) && (spec1->parID == spec2->parID) && (EqualString(&spec1->name,&spec2->name,false,false)))
- returnVal = true;
- return(returnVal);
- }
-
- void SpinCursor(void)
- {
- static short cID = kBaseMadFred;
- SetCursor(*GetCursor(cID));
- cID++;
- if(cID > 137)cID = kBaseMadFred;
- }
-
- Boolean IsMyWindow(WindowPtr theWind)
- {
- return((((WindowPeek)theWind)->windowKind == kAEStatusWindow) || (((WindowPeek)theWind)->windowKind == kClipboardWindow) || (((WindowPeek)theWind)->windowKind == kDocumentWindow));
- }
-
- Boolean IsModalFront(void)
- {
- Boolean retVal = false;
- WindowPtr theWindow = FrontWindow();
- #define peekit ((WindowPeek)theWindow)->windowKind
- if(peekit == plainDBox || peekit == altDBoxProc || peekit == movableDBoxProc)
- retVal = true;
- #undef peekit
- return(retVal);
- }
-
- #undef __GUTILS__
-